﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.Caching;
using System.Web.Configuration;

namespace Web.Enhancements.Rest
{
    internal class OutputCacheInitializer
    {
        internal OutputCacheInitializer()
        {
        }

        internal virtual void InitOutputCache(WebRestCacheParameters cacheSettings)
        {
            HttpContext context = HttpContext.Current;
            HttpCachePolicy cache = context.Response.Cache;

            if (cacheSettings.Enabled && cacheSettings.Duration > 0)
            {
                int seconds = cacheSettings.Duration;
                List<string> varyByParam = cacheSettings.VaryByParamItems;
                OutputCacheLocation location = cacheSettings.Location;
                HttpCacheability cacheability = HttpCacheability.Server;
#if TRACE
                System.Diagnostics.Trace.WriteLine(string.Format("Setting up the REST-service cache for duration of {0} sec.", seconds.ToString()));
#endif

                switch (location)
                {
                    case OutputCacheLocation.Any:
                        cacheability = HttpCacheability.Public;
                        break;
                    case OutputCacheLocation.Client:
                        cacheability = HttpCacheability.Private;
                        break;
                    case OutputCacheLocation.Downstream:
                        cacheability = HttpCacheability.Public;
                        cache.SetNoServerCaching();
                        break;
                    case OutputCacheLocation.Server:
                        cacheability = HttpCacheability.Server;
                        break;
                    case OutputCacheLocation.None:
                        cacheability = HttpCacheability.NoCache;
                        break;
                    case OutputCacheLocation.ServerAndClient:
                        cacheability = HttpCacheability.ServerAndPrivate;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException("Invalid cache settings location.");
                }
                cache.SetCacheability(cacheability);
                if (location != OutputCacheLocation.None)
                {
                    cache.SetExpires(context.Timestamp.AddSeconds((double)seconds));
                    cache.SetMaxAge(new TimeSpan(0, 0, seconds));
                    cache.SetValidUntilExpires(true);
                    cache.SetLastModified(context.Timestamp);
                    if (location != OutputCacheLocation.Client)
                    {
                        if (location != OutputCacheLocation.Downstream)
                        {
                            if (varyByParam.Count == 0)
                                cache.VaryByParams.IgnoreParams = true;
                            else
                            {
                                foreach (string varyParam in varyByParam)
                                    cache.VaryByParams[varyParam.Trim()] = true;
                            }
                        }
                    }
                }
            }
            else
            {
                cache.SetExpires(DateTime.Now.AddDays(-1000));
                cache.SetCacheability(HttpCacheability.NoCache);
                cache.SetValidUntilExpires(false);
                cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            }
        }
    }
}
